package io.xxx.omni.osc.sync

import com.alibaba.fastjson.JSONObject
import io.xxx.omni.osc.common.toJSONObject
import io.xxx.omni.osc.common.toLocalDateTime
import io.xxx.omni.osc.common.zoneOffset
import io.xxx.omni.osc.domain.Document
import io.xxx.omni.osc.domain.DocumentType
import io.xxx.omni.osc.domain.PlatformIdentity
import io.xxx.omni.osc.domain.Store
import io.xxx.omni.osc.sdk.XhsClient
import org.springframework.stereotype.Component
import java.util.stream.Collectors

/**
 * 小红书
 */
// https://school.xiaohongshu.com/open/quick-start/sign.html
abstract class XhsPorter : GenericPageDocumentPorter(), PlatformIdentity.XiaoHongShu {

    protected abstract val path: String

    override fun getResponse(context: JobContext, pageNo: Int, hasTotal: Boolean): JSONObject {
        val request = buildRequest(context, pageNo)
        val client = applicationContext.getBean(XhsClient::class.java)
        return client.execute(context.store, path, request)
    }

    override fun getCount(context: JobContext, response: JSONObject): Int = response.getInteger("total_number")

    protected abstract fun buildRequest(context: JobContext, pageNo: Int): Map<String, Any>
}

// 订单
// https://school.xiaohongshu.com/open/package/packages-list.html
@Component
class XhsTradePorter : XhsPorter() {

    override val documentType = DocumentType.TRADE

    override val path = "/ark/open_api/v0/packages"

    override fun getParameters(store: Store) = listOf("waiting", "shipped", "received") to false

    override fun buildDocuments(context: JobContext, response: JSONObject): List<Document> {
        return response
            .getJSONArray("package_list")
            .map {
                val value = it.toJSONObject()
                value.getString("package_id") to value.getLong("update_time").toLocalDateTime()
            }
            .parallelStream()
            .map {
                val client = applicationContext.getBean(XhsClient::class.java)
                val result = client.execute(context.store, "/ark/open_api/v0/packages/${it.first}")
                val value = result.toJSONObject()
                val sn = value.getString("package_id")
                val status = value.getString("status")
                val modified = it.second
                Document(sn, status, modified, value)
            }
            .collect(Collectors.toList())
    }

    override fun buildRequest(context: JobContext, pageNo: Int): Map<String, Any> {
        val (_, startTime, endTime, parameter) = context
        return mapOf(
            "status" to parameter!!,
            "page_no" to pageNo,
            "page_size" to pageSize,
            "start_time" to startTime.toEpochSecond(zoneOffset),
            "end_time" to endTime.toEpochSecond(zoneOffset),
            "time_type" to "updated_at",    // 订单创建时间：created_at，订单确认时间：confirmed_at，订单更新时间：updated_at
        )
    }
}

// 退单
// https://school.xiaohongshu.com/open/refund/refund-list.html
@Component
class XhsRefundPorter : XhsPorter() {

    override val documentType = DocumentType.REFUND

    override val path = "/ark/open_api/v0/refund/list"

    override fun buildDocuments(context: JobContext, response: JSONObject): List<Document> {
        return response
            .getJSONArray("refund_list")
            .map {
                val value = it.toJSONObject()
                val modified = value.getLong("updated_at").toLocalDateTime()
                value.getString("returns_id") to modified
            }
            .parallelStream()
            .map {
                val client = applicationContext.getBean(XhsClient::class.java)
                val jsonObject = client.execute(context.store, "/ark/open_api/v0/refund/${it.first}")

                @Suppress("unchecked_cast")
                val value = JSONObject(jsonObject as Map<String, Any>)
                val sn = value.getString("returns_id")
                val rsn = value.getString("package_id")
                val status = value.getString("status")
                val modified = it.second
                Document(sn, rsn, status, modified, value)
            }
            .collect(Collectors.toList())
    }

    override fun buildRequest(context: JobContext, pageNo: Int): Map<String, Any> {
        val (_, startTime, endTime) = context
        return mapOf(
            "page" to pageNo,
            "page_size" to pageSize,
            "start_time" to startTime.toEpochSecond(zoneOffset),
            "end_time" to endTime.toEpochSecond(zoneOffset),
        )
    }
}